package com.sunda.spmswms.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmscommon.feign.IFeignServiceCommon;
import com.sunda.spmswms.entity.WhsDump;
import com.sunda.spmswms.entity.WhsDumpDtl;
import com.sunda.spmswms.entity.WhsInventoryInfo;
import com.sunda.spmswms.entity.WhsStorageInventory;
import com.sunda.spmswms.mapper.WhsDumpMapper;
import com.sunda.spmswms.service.*;
import feign.FeignException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import static com.sunda.spmscommon.Constans.*;
import static com.sunda.spmscommon.constant.CommonConstant.WHS_DUMP_DELETE;
import static com.sunda.spmscommon.constant.CommonConstant.WHS_DUMP_DONE;
import static com.sunda.spmscommon.constant.CommonConstant.*;

/**
 * <p>
 * 转储任务表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-06-29
 */
@Service
public class WhsDumpServiceImpl extends ServiceImpl<WhsDumpMapper, WhsDump> implements IWhsDumpService {

    @Autowired
    IWhsStorageInventoryService iWhsStorageInventoryService;

    @Autowired
    IWhsInventoryInfoService iWhsInventoryInfoService;

    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    @Autowired
    ISapDeliveryNoteLogService iSapDeliveryNoteLogService;

    @Autowired
    IWhsDumpDtlService iWhsDumpDtlService;

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;

    @Override
    public WhsDump getWhsDumpByUuid(String whsDumpUuid) {
        if (StringUtils.isEmpty(whsDumpUuid)){
            return null;
        }
        return this.baseMapper.selectOne(new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid));
    }

    /**
     {
     "beginDate": "2021-08-10",
     "endDate": "2021-08-14",
     "whsDumpNo": "",
     "goodsType": "",
     "werksDumpOut": "",
     "whsLocationCodeDumpOut": "",
     "spmsStatus": "",
     "sapDumpOutNo": "",
     "sapDeliveryNote": "",
     "werksDumpIn": "",
     "whsLocationCodeDumpIn": "",
     "pageNo": 1,
     "pageSize": 20
     }
     * @param doc
     * @return
     */
    @Override
    public Page<Map<String, Object>> getWhsDumpListPage(JSONObject doc) {
        try {
            int pageNo = StringUtils.isEmpty(doc.getString("pageNo")) ? 1 : doc.getInteger("pageNo");
            int pageSize = StringUtils.isEmpty(doc.getString("pageSize")) ? 20 : doc.getInteger("pageSize");
            String whsDumpNo = StringUtils.isEmpty(doc.getString("whsDumpNo")) ? null : doc.getString("whsDumpNo");
            String goodsType = StringUtils.isEmpty(doc.getString("goodsType")) ? null : doc.getString("goodsType");
            String werksDumpOut = StringUtils.isEmpty(doc.getString("werksDumpOut")) ? null : doc.getString("werksDumpOut");
            String whsLocationCodeDumpOut = StringUtils.isEmpty(doc.getString("whsLocationCodeDumpOut")) ? null : doc.getString("whsLocationCodeDumpOut");
            String spmsStatus = StringUtils.isEmpty(doc.getString("spmsStatus")) ? null : doc.getString("spmsStatus");
            String sapDumpOutNo = StringUtils.isEmpty(doc.getString("sapDumpOutNo")) ? null : doc.getString("sapDumpOutNo");
            String sapDeliveryNote = StringUtils.isEmpty(doc.getString("sapDeliveryNote")) ? null : doc.getString("sapDeliveryNote");
            String werksDumpIn = StringUtils.isEmpty(doc.getString("werksDumpIn")) ? null : doc.getString("werksDumpIn");
            String whsLocationCodeDumpIn = StringUtils.isEmpty(doc.getString("whsLocationCodeDumpIn")) ? null : doc.getString("whsLocationCodeDumpIn");
            String beginDate = StringUtils.isEmpty(doc.getString("beginDate")) ? null : doc.getString("beginDate");
            String endDate = StringUtils.isEmpty(doc.getString("endDate")) ? null : doc.getString("endDate");
            Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
            List<Map<String, Object>> pageMaData = this.baseMapper.pageWhsDumpDataMap(pages, whsDumpNo, goodsType, werksDumpOut, whsLocationCodeDumpOut,
                    spmsStatus, sapDumpOutNo, sapDeliveryNote, werksDumpIn, whsLocationCodeDumpIn, beginDate, endDate);
            pages.setRecords(pageMaData);
            return pages;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * SPMS转储单据状态（0删除；1草稿；2转出可执行；3转出完成；4提交SAP获取PO成功；5提交SAP获取PO失败；
     * 6提交SAP获取DN成功；7提交SAP获取DN失败；8转出已撤销；）
     * 当前状态：1，2，5 可调用此接口
     * @param doc
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult saveWhsDump(JSONObject doc, String userId) {
        ResponseResult checkResult = checkDataValidate(doc);
        if (checkResult.getCode() != 200){
            return checkResult;
        }
        try {
            JSONObject whsDumpObject = doc.getJSONObject("whsDump");
            JSONArray whsDumpArray = doc.getJSONArray("whsDumpDtl");
            String whsDumpUuid = whsDumpObject.getString("whsDumpUuid");
            String targetStatus = whsDumpObject.getString("targetStatus");
            WhsDump whsDump = whsDumpObject.toJavaObject(WhsDump.class);
            if (StringUtils.isEmpty(whsDumpUuid)){
                whsDumpUuid = UUID.randomUUID().toString().toLowerCase().replaceAll("-","");
                int resp = createWhsDumpAndDtl(whsDumpUuid, whsDump, whsDumpArray, targetStatus, userId);
                if (resp < 0){
                    throw new RuntimeException("转储任务创建失败");
                }
                return ResponseResult.success()
                        .add("whsDumpList", getWhsDumpByUuid(whsDumpUuid))
                        .add("whsDumpDtl", iWhsDumpDtlService.getWhsDumpDtlList(whsDumpUuid));
            }else {
                if ("1".equals(targetStatus) || "2".equals(targetStatus)
                        || "3".equals(targetStatus) || "5".equals(targetStatus)){
                    int resp = updateWhsDumpAndDtl(whsDump, whsDumpArray, targetStatus, userId);
                    if (resp < 0){
                        throw new RuntimeException("转储任务更新失败");
                    }
                    return ResponseResult.success()
                            .add("whsDumpList", getWhsDumpByUuid(whsDumpUuid))
                            .add("whsDumpDtl", iWhsDumpDtlService.getWhsDumpDtlList(whsDumpUuid));
                }
                return ResponseResult.error("当前状态禁止此操作");
            }
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("请求错误");
        }
    }

    int updateWhsDumpAndDtl(WhsDump whsDump, JSONArray whsDumpArray, String targetStatus, String userId){
        try {
            String whsDumpUuid = whsDump.getWhsDumpUuid();
            QueryWrapper<WhsDump> queryWrapper = new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
            whsDump.setSpmsStatus(targetStatus);
            this.baseMapper.update(whsDump, queryWrapper);
            if (whsDumpArray.size() > 0){
                iWhsDumpDtlService.deleteWhsDumpDtl(whsDumpUuid);
                for (int i = 0; i < whsDumpArray.size(); i++){
                    JSONObject whsDumpDtlObject = whsDumpArray.getJSONObject(i);
                    WhsDumpDtl whsDumpDtl = whsDumpDtlObject.toJavaObject(WhsDumpDtl.class);
                    whsDumpDtl.setActualOutStorage(StringUtils.isNotEmpty(whsDumpDtlObject.getString("actualOutStorage"))? whsDumpDtlObject.getJSONArray("actualOutStorage").toJSONString():"[]");
                    whsDumpDtl.setActualInStorage(StringUtils.isNotEmpty(whsDumpDtlObject.getString("actualInStorage"))? whsDumpDtlObject.getJSONArray("actualInStorage").toJSONString():"[]");
                    whsDumpDtl.setWhsDumpUuid(whsDumpUuid);
                    iWhsDumpDtlService.createWhsDumpDtl(whsDumpDtl);
                }
            }
            addWhsDumpOperateLog(whsDumpUuid, userId, targetStatus);
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    int createWhsDumpAndDtl(String whsDumpUuid, WhsDump whsDump, JSONArray whsDumpArray, String targetStatus, String userId){
        try {
            whsDump.setSpmsStatus(targetStatus);
            whsDump.setWhsDumpUuid(whsDumpUuid);
            this.baseMapper.insert(whsDump);
            if (whsDumpArray.size() > 0){
                for (int i = 0; i < whsDumpArray.size(); i++){
                    JSONObject whsDumpDtlObject = whsDumpArray.getJSONObject(i);
                    WhsDumpDtl whsDumpDtl = whsDumpDtlObject.toJavaObject(WhsDumpDtl.class);
                    whsDumpDtl.setActualOutStorage(StringUtils.isNotEmpty(whsDumpDtlObject.getString("actualOutStorage"))? whsDumpDtlObject.getJSONArray("actualOutStorage").toJSONString():"[]");
                    whsDumpDtl.setActualInStorage(StringUtils.isNotEmpty(whsDumpDtlObject.getString("actualInStorage"))? whsDumpDtlObject.getJSONArray("actualInStorage").toJSONString():"[]");
                    whsDumpDtl.setWhsDumpUuid(whsDumpUuid);
                    iWhsDumpDtlService.createWhsDumpDtl(whsDumpDtl);
                }
            }
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_CREATE);
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    ResponseResult checkDataValidate(JSONObject doc){
        try {
            JSONObject whsDumpObject = doc.getJSONObject("whsDump");
            JSONArray whsDumpArray = doc.getJSONArray("whsDumpDtl");
            String whsDumpUuid = whsDumpObject.getString("whsDumpUuid");
            String currentStatus = whsDumpObject.getString("currentStatus");
            String targetStatus = whsDumpObject.getString("targetStatus");
            WhsDump whsDump = whsDumpObject.toJavaObject(WhsDump.class);
            if (StringUtils.isNotEmpty(whsDumpUuid)){
                if (!("1".equals(currentStatus) || "2".equals(currentStatus) || "5".equals(currentStatus))){
                    return ResponseResult.error("当前状态禁止此操作");
                }
                QueryWrapper<WhsDump> queryWrapper = new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
                WhsDump whsDumpEntity = this.baseMapper.selectOne(queryWrapper);
                if (!currentStatus.equals(whsDumpEntity.getSpmsStatus())){
                    return ResponseResult.error("单据状态已更新请刷新后重试");
                }
                if (WHS_DUMP_EXECUTE.equals(targetStatus) || WHS_DUMP_GET_PO_ERROR.equals(targetStatus)){
                    if (whsDumpArray.size() == 0 || StringUtils.isEmpty(whsDump.getWerksDumpOut()) || StringUtils.isEmpty(whsDump.getWhsLocationCodeDumpOut())){
                        return ResponseResult.error("请求参数错误");
                    }
                    for (int i = 0; i < whsDumpArray.size(); i++){
                        JSONObject whsDumpDtlObject = whsDumpArray.getJSONObject(i);
                        WhsDumpDtl whsDumpDtl = whsDumpDtlObject.toJavaObject(WhsDumpDtl.class);
                        whsDumpDtl.setActualOutStorage(StringUtils.isNotEmpty(whsDumpDtlObject.getString("actualOutStorage"))? whsDumpDtlObject.getJSONArray("actualOutStorage").toJSONString():"[]");
                        //whsDumpDtl.setActualInStorage(StringUtils.isNotEmpty(whsDumpDtlObject.getString("actualInStorage"))? whsDumpDtlObject.getJSONArray("actualInStorage").toJSONString():"[]");
                        String boxNote = whsDumpDtl.getBoxNote();
                        double actualOutQty = whsDumpDtl.getActualOutQty() != null ? whsDumpDtl.getActualOutQty() : 0;
                        if (actualOutQty > 0){
                            JSONArray storageInfo = JSONArray.parseArray(whsDumpDtl.getActualOutStorage());
                            if (storageInfo == null || storageInfo.size() == 0){
                                return ResponseResult.error("请求参数错误");
                            }
                            String storageUuid = storageInfo.getJSONObject(0).getString("storageUuid");
                            String storageNo = storageInfo.getJSONObject(0).getString("storageNo");
                            if (StringUtils.isEmpty(storageUuid) || StringUtils.isEmpty(boxNote)){
                                return ResponseResult.error("请求参数错误");
                            }
                            WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getStorageBoxNote(storageUuid, boxNote);
                            if (null == whsStorageInventory){
                                return ResponseResult.error("箱码" + boxNote + "在储位" + storageUuid + "-" + storageNo + "不存在");
                            }
                            WhsInventoryInfo whsInventoryInfo = iWhsInventoryInfoService.getWhsInventoryInfoByBoxNote(boxNote, whsDump.getWerksDumpOut(), whsDump.getWhsLocationCodeDumpOut());
                            if (null == whsInventoryInfo){
                                return ResponseResult.error("箱码" + boxNote + "在仓库" + whsDump.getWerksDumpOut() + "-" + whsDump.getWhsLocationCodeDumpOut() + "不存在");
                            }
                        }
                    }
                }
            }
            return ResponseResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error(e.getMessage());
        }
    }
    // SPMS转储单据状态(0删除；1草稿；2转出可执行；3转出完成；4提交SAP获取PO成功；5提交SAP获取PO失败；
    // 6提交SAP获取DN成功；7提交SAP获取DN失败；8转出已撤销；)
    void addWhsDumpOperateLog(String whsDumpUuid, String userId, String targetStatus){
        if (WHS_DUMP_DELETE.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_DELETE_MSG);
        }
        if (WHS_DUMP_SAVE.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_SAVE_MSG);
        }
        if (WHS_DUMP_EXECUTE.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_EXECUTE_MSG);
        }
        if (WHS_DUMP_DONE.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_DONE_MSG);
        }
        if (WHS_DUMP_GET_PO.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_GET_PO_MSG);
        }
        if (WHS_DUMP_GET_PO_ERROR.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_GET_PO_ERROR_MSG);
        }
        if (WHS_DUMP_GET_DN.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_GET_DN_MSG);
        }
        if (WHS_DUMP_GET_DN_ERROR.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_GET_DN_ERROR_MSG);
        }
        if (WHS_DUMP_CANCEL.equals(targetStatus)){
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_CANCEL_MSG);
        }

    }

    /***
     * SPMS_STATUS: SPMS转储单据状态（0删除；1草稿；2转出可执行；3转出完成；4转出提交SAP成功-计算库存-获取sap采购订单号；5转出提交SAP失败；
     * 6转入可执行；7转入完成；8转入提交SAP成功-计算库存；9转入提交SAP失败；10完成；11转出提交SAP成功-获取sap交货单号）
     *
     * 0删除；1草稿；2转出可执行；3转出完成；4提交SAP获取PO成功；5提交SAP获取PO失败；6提交SAP获取DN成功；7提交SAP获取DN失败；8转出已撤销；
     * WHS_DUMP_UUID = ef1cf3d2a4ad4fb4a79284a52f32f1c8
     * @param whsDumpUuid
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult whsDumpOutToSap(String whsDumpUuid, String dumpOutSapDate, String userId) {
        try {
            ResponseResult checkResult = checkWhsDumpOut(whsDumpUuid, dumpOutSapDate);
            if (checkResult.getCode() != 200){
                return checkResult;
            }
            WhsDump whsDump = this.baseMapper.selectOne(new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid));
            List<WhsDumpDtl> whsDumpDtlList = iWhsDumpDtlService.getWhsDumpDtlListByUuid(whsDumpUuid);
            String spmsStatus = whsDump.getSpmsStatus();
            Map<String, Object> Head = this.baseMapper.dataToDapHead(whsDumpUuid);
            List<Map<String, Object>> IT_XHEAD = this.baseMapper.dataToDapBoxNote(whsDumpUuid);
            List<Map<String, Object>> IT_POITEM = this.baseMapper.dataToDapMaterial(whsDumpUuid);
            if (Head == null || IT_XHEAD == null || IT_POITEM == null || IT_XHEAD.size() == 0 || IT_POITEM.size() == 0){
                return ResponseResult.error().add("error", "空运人带数据提交SAP时，获取详情数据出错");
            }
            /** SPMS转储单据状态（0删除；1草稿；2转出可执行；3转出完成；4提交SAP获取PO成功；5提交SAP获取PO失败；
             *  6提交SAP获取DN成功；7提交SAP获取DN失败；8转出已撤销；）
             *
             * 第一次提交前状态为：3、5
             * 	成功后状态：4
             * 	失败后状态：5
             *
             * 第二次提交前状态为：4、7
             * 	成功后状态：6，更新库存计算
             * 	失败后状态：7
             *
             * 撤销前状态为：6
             * 	成功后状态：8，更新库存计算
             * 	失败忽略状态更新
             * */
            if (WHS_DUMP_DONE.equals(spmsStatus) || WHS_DUMP_GET_PO_ERROR.equals(spmsStatus)){
                JSONObject dataToSapGetPOJson = dataToSapGetPO(Head, IT_XHEAD, IT_POITEM);
                JSONObject sapReturnedData = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSapGetPOJson));
                if (!"S".equals(sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_TYPE"))){
                    updateWhsDumpStatus(whsDumpUuid, WHS_DUMP_GET_PO_ERROR, "", "", "", "", "");
                    iSapDeliveryNoteLogService.insertSapRequestRecord(whsDumpUuid, userId, WHS_DUMP_GET_PO_ERROR_MSG, sapReturnedData.toJSONString(), dataToSapGetPOJson.toJSONString());
                    return ResponseResult.error().add("sapReturnedData", sapReturnedData).add("dataToSap", dataToSapGetPOJson);
                }
                String PO = sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_EBELN");
                updateWhsDumpStatus(whsDumpUuid, WHS_DUMP_GET_PO, PO, "", "", "", "");
                iSapDeliveryNoteLogService.insertSapRequestRecord(whsDumpUuid, userId, WHS_DUMP_GET_PO_MSG, sapReturnedData.toJSONString(), dataToSapGetPOJson.toJSONString());
                return ResponseResult.success()
                        .add("sapReturnedData", sapReturnedData)
                        .add("dataToSap", dataToSapGetPOJson)
                        .add("whsDump", this.baseMapper.selectOne(new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid)));
            }
            if (WHS_DUMP_GET_PO.equals(spmsStatus) || WHS_DUMP_GET_DN_ERROR.equals(spmsStatus)){
                /** 空运人带 Z_SPMS_DN_POST 获取DN时，新建传值由 I 改为 01； ———— 20211209 */
                JSONObject dataToSapGetDNJson = dataToSapGetDN("01", dumpOutSapDate, whsDump.getSapDumpOutNo(), "", whsDump.getWhsLocationCodeDumpOut());
                JSONObject sapReturnedData = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSapGetDNJson));
                if (!"S".equals(sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_TYPE"))){
                    updateWhsDumpStatus(whsDumpUuid, WHS_DUMP_GET_DN_ERROR, "", "", dumpOutSapDate, "", "");
                    iSapDeliveryNoteLogService.insertSapRequestRecord(whsDumpUuid, userId, WHS_DUMP_GET_DN_ERROR_MSG, sapReturnedData.toJSONString(), dataToSapGetDNJson.toJSONString());
                    return ResponseResult.error().add("sapReturnedData", sapReturnedData).add("dataToSap", dataToSapGetDNJson);
                }
                String DN = sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_VBELN");
                String sapWhsOutNo = sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_VBELN");
                String sapWhsOutYear = sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MJAHR");
                String werks = whsDump.getWerksDumpOut();
                String whsLocationCode = whsDump.getWhsLocationCodeDumpOut();
                for (WhsDumpDtl dumpDtl : whsDumpDtlList){
                    String boxNote = dumpDtl.getBoxNote();
                    String actualOutStorage = dumpDtl.getActualOutStorage();
                    JSONArray storageArray = JSON.parseArray(actualOutStorage);
                    String storageUuid = storageArray.getJSONObject(0).getString("storageUuid");
                    ResponseResult updateWhsStorageInventory = iWhsStorageInventoryService.updateStorageInvX(storageUuid, boxNote, 1, "sub");
                    if (updateWhsStorageInventory.getCode() != 200){
                        System.out.println("whsDumpOutToSap 转储任务移出更新储位库存出错：" + updateWhsStorageInventory.toString());
                        throw new Exception("whsDumpOutToSap 转储任务移出更新储位库存出错：" + updateWhsStorageInventory.toString());
                    }
                    iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, "", boxNote, 1,"16", whsDumpUuid, SPARE_PARTS_OUT_STORAGE, userId, "转储任务箱码出储位", werks, whsLocationCode);

                    ResponseResult updateWhsInventory = iWhsInventoryInfoService.updateWhsInventoryX(werks, whsLocationCode, boxNote, 1, "sub", userId);
                    if (updateWhsInventory.getCode() != 200){
                        System.out.println("whsDumpOutToSap 转储任务移出更新仓库库存出错：" + updateWhsInventory.toString());
                        throw new Exception("whsDumpOutToSap 转储任务移出更新仓库库存出错：" + updateWhsInventory.toString());
                    }
                    iWhsOperateLogService.insertWhsOperateLog("1", "", "", boxNote, 1,"15", whsDumpUuid, SPARE_PARTS_OUT_WHS, userId, "转储任务箱码出仓库", werks, whsLocationCode);

                }

                updateWhsDumpStatus(whsDumpUuid, WHS_DUMP_GET_DN, "", DN, dumpOutSapDate, sapWhsOutNo, sapWhsOutYear);
                iSapDeliveryNoteLogService.insertSapRequestRecord(whsDumpUuid, userId, WHS_DUMP_GET_DN_MSG, sapReturnedData.toJSONString(), dataToSapGetDNJson.toJSONString());
                return ResponseResult.success()
                        .add("sapReturnedData", sapReturnedData)
                        .add("dataToSap", dataToSapGetDNJson)
                        .add("whsDump", this.baseMapper.selectOne(new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid)));
            }
            return ResponseResult.error().add("error", "单据当前状态禁止此操作");
        }catch (FeignException e){
            e.printStackTrace();
            return ResponseResult.error("请求SAP失败 FeignException").add("error", e.getMessage());
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("提交SAP失败 Exception").add("error", e.getMessage());
        }
    }

    /** 0删除；1草稿；2转出可执行；3转出完成；4提交SAP获取PO成功；5提交SAP获取PO失败；
     * 6提交SAP获取DN成功；7提交SAP获取DN失败；8转出已撤销；
     */
    ResponseResult checkWhsDumpOut (String whsDumpUuid, String dumpOutSapDate){
        if (StringUtils.isEmpty(whsDumpUuid)){
            return ResponseResult.error().add("error", "请求参数不能为空.");
        }
        WhsDump whsDump = this.baseMapper.selectOne(new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid));
        if (whsDump == null || !(WHS_DUMP_DONE.equals(whsDump.getSpmsStatus()) || WHS_DUMP_GET_PO_ERROR.equals(whsDump.getSpmsStatus()) ||
                WHS_DUMP_GET_PO.equals(whsDump.getSpmsStatus()) || WHS_DUMP_GET_DN_ERROR.equals(whsDump.getSpmsStatus()))){
            return ResponseResult.error().add("error", "空运人带任务当前状态禁止提交SAP.");
        }
        String spmsStatus = whsDump.getSpmsStatus();
        String werks = whsDump.getWerksDumpOut();
        String whsLocationCode = whsDump.getWhsLocationCodeDumpOut();
        List<WhsDumpDtl> whsDumpDtlList = iWhsDumpDtlService.getWhsDumpDtlListByUuid(whsDumpUuid);
        if (whsDumpDtlList == null || whsDumpDtlList.size() == 0){
            return ResponseResult.error().add("error", "空运人带任务不存在或没有实际操作数量大于0的行");
        }
        /** 3，5，4，7 都需要校验库存是否足够；4，7 还需校验 采购订单号不能为空； */
        if (WHS_DUMP_GET_PO.equals(spmsStatus) || WHS_DUMP_GET_DN_ERROR.equals(spmsStatus)){
            if (StringUtils.isEmpty(whsDump.getSapDumpOutNo())){
                return ResponseResult.error().add("error", "SAP采购订单号-SAP_DUMP_OUT_NO为空，不能提交SAP");
            }
            if (StringUtils.isEmpty(dumpOutSapDate) || "Invalid date".equals(dumpOutSapDate)){
                return ResponseResult.error().add("error", "过账日期不合法或不能为空 dumpOutSapDate：" + dumpOutSapDate);
            }
        }
        if (WHS_DUMP_GET_PO.equals(spmsStatus) || WHS_DUMP_GET_DN_ERROR.equals(spmsStatus) ||
                WHS_DUMP_GET_PO.equals(whsDump.getSpmsStatus()) || WHS_DUMP_GET_DN_ERROR.equals(whsDump.getSpmsStatus())){
            for (WhsDumpDtl dumpDtl : whsDumpDtlList){
                String boxNote = dumpDtl.getBoxNote();
                String actualOutStorage = dumpDtl.getActualOutStorage();
                if (StringUtils.isEmpty(boxNote) || StringUtils.isEmpty(actualOutStorage)){
                    return ResponseResult.error().add("error", "空运人带行数据箱码或实出储位信息不正确");
                }
                JSONArray storageArray = JSON.parseArray(actualOutStorage);
                if (storageArray.size() == 0){
                    ResponseResult.error().add("error", "空运人带行数据实出储位信息不正确");
                }
                String storageUuid = storageArray.getJSONObject(0).getString("storageUuid");
                String storageNo = storageArray.getJSONObject(0).getString("storageNo");
                if (StringUtils.isEmpty(storageUuid)){
                    ResponseResult.error().add("error", "空运人带行数据实出储位信息不正确");
                }
                String whsInventoryQty = iWhsInventoryInfoService.getQuantityByBoxNote(werks, whsLocationCode, boxNote);
                if (StringUtils.isEmpty(whsInventoryQty)){
                    return ResponseResult.error().add("error", "箱码" + boxNote + "在仓库" + werks + whsLocationCode + "库存不足，转出失败");
                }
                String whsStorageInventoryQty = iWhsStorageInventoryService.getAvailableQtyByUuidBoxNote(storageUuid, boxNote);
                if (StringUtils.isEmpty(whsStorageInventoryQty)){
                    return ResponseResult.error().add("error", "箱码" + boxNote + "在储位" + werks + whsLocationCode + storageNo + "库存不足，转出失败");
                }
            }
        }
        return ResponseResult.success();
    }

    JSONObject dataToSapGetPO (Map<String, Object> Head, List<Map<String, Object>> IT_XHEAD, List<Map<String, Object>> IT_POITEM){
        JSONObject doc = new JSONObject();

        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        JSONObject MapItems = new JSONObject();

        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());

        MapItems.put("IT_POITEM", IT_POITEM);
        MapItems.put("IT_XHEAD", IT_XHEAD);

        REQUEST_DATA.put("Head", Head);
        REQUEST_DATA.put("MapItems", MapItems);
        REQUEST_DATA.put("Operation", "Z_SPMS_CREATE_STO");
        REQUEST_DATA.put("Type", "CREATE_STO");

        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);

        doc.put("REQUEST", REQUEST);
        return doc;
    }

    /** iFlag = I 新增，D 删除；postingDate 过账日期；purchaseOrder 采购订单号；deliveryNote DN交货单号； */
    JSONObject dataToSapGetDN(String iFlag, String postingDate, String purchaseOrder, String deliveryNote, String whsLocationCodeDumpOut){
        JSONObject obj = new JSONObject();

        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        JSONObject Head = new JSONObject();

        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());

        Head.put("iFlag", iFlag);
        Head.put("iBudat", postingDate.replaceAll("-", ""));
        Head.put("iEbeln", StringUtils.isEmpty(purchaseOrder) ? "" : purchaseOrder);
        Head.put("iVbeln", StringUtils.isEmpty(deliveryNote) ? "" : deliveryNote);
        Head.put("iLgort", StringUtils.isEmpty(whsLocationCodeDumpOut) ? "" : whsLocationCodeDumpOut);

        REQUEST_DATA.put("Head", Head);
        REQUEST_DATA.put("Operation", "Z_SPMS_DN_POST");
        REQUEST_DATA.put("Type", "DN_POST");

        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        obj.put("REQUEST", REQUEST);
        return obj;
    }

    /**
     * @param whsDumpUuid
     * @param targetStatus
     */
    public void updateWhsDumpStatus (String whsDumpUuid, String targetStatus, String sapPurchaseOrder, String sapDeliveryNote,
                                     String postingDate, String sapWhsOutNo, String sapWhsOutYear){
        WhsDump whsDump = new WhsDump();
        whsDump.setSpmsStatus(targetStatus);
        if (StringUtils.isNotEmpty(sapPurchaseOrder)){
            whsDump.setSapDumpOutNo(sapPurchaseOrder);
        }
        if (StringUtils.isNotEmpty(sapDeliveryNote)){
            whsDump.setSapDeliveryNote(sapDeliveryNote);
        }
        if (StringUtils.isNotEmpty(postingDate)){
            whsDump.setDumpOutSapDate(postingDate);
        }
        if (StringUtils.isNotEmpty(sapWhsOutNo)){
            whsDump.setSapWhsOutNo(sapWhsOutNo);
        }
        if (StringUtils.isNotEmpty(sapWhsOutYear)){
            whsDump.setSapWhsOutYear(sapWhsOutYear);
        }
        this.baseMapper.update(whsDump, new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid));
    }

    @Override
    public ResponseResult deleteWhsDump(String whsDumpUuid, String userId) {
        if (StringUtils.isEmpty(whsDumpUuid)){
            return ResponseResult.error("请求参数不能为空");
        }
        QueryWrapper<WhsDump> queryWrapper = new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        WhsDump whsDump = this.baseMapper.selectOne(queryWrapper);
        String currentStatus = whsDump.getSpmsStatus();
        if (whsDump == null || currentStatus == null){
            return ResponseResult.error("空运人带任务查询不存在");
        }
        if (WHS_DUMP_DELETE.equals(currentStatus)){
            return ResponseResult.success("空运人带任务已删除");
        }
        if (!WHS_DUMP_SAVE.equals(currentStatus) && !WHS_DUMP_EXECUTE.equals(currentStatus)
                && !WHS_DUMP_DONE.equals(currentStatus) && !WHS_DUMP_GET_PO_ERROR.equals(currentStatus)){
            return ResponseResult.error("当前任务状态不能删除");
        }
        whsDump.setSpmsStatus(WHS_DUMP_DELETE);
        this.baseMapper.update(whsDump, queryWrapper);
        iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsDumpUuid, userId, WHS_DUMP_DELETE_MSG);
        return ResponseResult.success();
    }

    /**
     * 空运人带任务从SAP撤销。0删除；1草稿；2转出可执行；3转出完成；4提交SAP获取PO成功；5提交SAP获取PO失败；
     * 6提交SAP获取DN成功；7提交SAP获取DN失败；8转出已撤销；
     * 1.只有 4，6，7 状态任务才可从SAP撤销；
     * 2.对于 4，7 撤销，PO 不能为空；对于 6 撤销，PO，DN 都不能为空
     * 3.撤销成功 更新状态为8；撤销失败不更新状态；
     * @param whsDumpUuid
     * @param userId
     * @return
     */
    @Override
    public ResponseResult cancelWhsDump(String whsDumpUuid, String cancelPostingDate, String userId) {
        ResponseResult checkResult = checkCancelValidate(whsDumpUuid, cancelPostingDate);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        QueryWrapper<WhsDump> queryWrapper = new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid);
        WhsDump whsDump = this.baseMapper.selectOne(queryWrapper);
        /** 空运人带 Z_SPMS_DN_POST 获取DN时，删除传值由 D 改为 02； ———— 20211209 */
        JSONObject cancelDataToSapFormat = dataToSapGetDN("02", cancelPostingDate, whsDump.getSapDumpOutNo(), whsDump.getSapDeliveryNote(), whsDump.getWhsLocationCodeDumpOut());
        JSONObject sapReturnedData = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(cancelDataToSapFormat));
        if (!"S".equals(sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_TYPE"))){
            //updateWhsDumpStatus(whsDumpUuid, WHS_DUMP_GET_PO_ERROR, "", "", "");
            iSapDeliveryNoteLogService.insertSapRequestRecord(whsDumpUuid, userId, WHS_DUMP_CANCEL_ERROR_MSG, sapReturnedData.toJSONString(), cancelDataToSapFormat.toJSONString());
            return ResponseResult.error().add("sapReturnedData", sapReturnedData).add("dataToSap", cancelDataToSapFormat);
        }

        /** 撤销成功后更新仓库库存，记录仓库库存增加日志；更新储位库存，记录储位库存增加日志； */
        cancelWhsDumpUpdateInventory(whsDump, userId);

        whsDump.setSpmsStatus(WHS_DUMP_CANCEL);
        whsDump.setCancelVoucherNumber(sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MBLNR"));
        whsDump.setCancelPostingDate(cancelPostingDate);
        whsDump.setCancelVoucherYear(sapReturnedData.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MJAHR"));
        this.baseMapper.update(whsDump, queryWrapper);

        iSapDeliveryNoteLogService.insertSapRequestRecord(whsDumpUuid, userId, WHS_DUMP_CANCEL_MSG, sapReturnedData.toJSONString(), cancelDataToSapFormat.toJSONString());
        return ResponseResult.success()
                .add("sapReturnedData", sapReturnedData)
                .add("dataToSap", cancelDataToSapFormat)
                .add("whsDump", this.baseMapper.selectOne(queryWrapper));
    }

    ResponseResult checkCancelValidate(String whsDumpUuid, String postingDate){
        if (StringUtils.isEmpty(whsDumpUuid) || StringUtils.isEmpty(postingDate)){
            return ResponseResult.error("请求参数错误");
        }
        WhsDump whsDump = this.baseMapper.selectOne(new QueryWrapper<WhsDump>().eq("WHS_DUMP_UUID", whsDumpUuid));
        if (whsDump == null){
            return ResponseResult.error("查询空运人带任务不存在");
        }
        String spmsStatus = whsDump.getSpmsStatus();
        if (StringUtils.isEmpty(spmsStatus)){
            return ResponseResult.error("查询空运人带任务不存在");
        }
        if (WHS_DUMP_GET_PO.equals(spmsStatus) || WHS_DUMP_GET_DN_ERROR.equals(spmsStatus)){
            if (StringUtils.isEmpty(whsDump.getSapDumpOutNo())){
                return ResponseResult.error("单据采购订单号PO为空，禁止撤销操作");
            }
        }else if(WHS_DUMP_GET_DN.equals(spmsStatus)){
            if (StringUtils.isEmpty(whsDump.getSapDeliveryNote())){
                return ResponseResult.error("单据交货单号DN为空，禁止撤销操作");
            }
        }else {
            return ResponseResult.error("当前空运人带任务状态不可撤销");
        }
        return ResponseResult.success();
    }

    /** 空运人带任务撤销成功之后，将任务明细中的箱数据，加到对应的仓库 和 储位 */
    ResponseResult cancelWhsDumpUpdateInventory(WhsDump whsDump, String userId){
        String werks = whsDump.getWerksDumpOut();
        String whsLocationCode = whsDump.getWhsLocationCodeDumpOut();
        String whsDumpUuid = whsDump.getWhsDumpUuid();
        List<WhsDumpDtl> whsDumpDtlList = iWhsDumpDtlService.getWhsDumpDtlListByUuid(whsDumpUuid);
        if (whsDumpDtlList != null && whsDumpDtlList.size() > 0){
            for (WhsDumpDtl whsDumpDtl : whsDumpDtlList){
                String boxNote = whsDumpDtl.getBoxNote();
                JSONArray storageInfo = JSONArray.parseArray(whsDumpDtl.getActualOutStorage());
                if (storageInfo != null && storageInfo.size() > 0){
                    /** 备件空运人带的储位信息数组，有效值长度只会是 1，此处不做遍历*/
                    // [{"storageUuid":"142d26caaf53404f87b6d0a59f64f7f2","qty":1,"storageNo":"A010101"}]
                    String storageUuid = storageInfo.getJSONObject(0).getString("storageUuid");
                    String storageNo = storageInfo.getJSONObject(0).getString("storageNo");
                    double qty = storageInfo.getJSONObject(0).getDoubleValue("qty");
                    iWhsInventoryInfoService.updateWhsInventoryX(werks, whsLocationCode, boxNote, qty, "add", userId);
                    iWhsOperateLogService.insertOperateLog("1", "", "", boxNote, qty, "17", whsDumpUuid, "转储撤销入仓库", userId, "转储撤销", werks, whsLocationCode, "");

                    iWhsStorageInventoryService.updateStorageInvX(storageUuid, boxNote, qty, "add");
                    iWhsOperateLogService.insertOperateLog("2", storageUuid, "", boxNote, qty, "18", whsDumpUuid, "转储撤销入储位", userId, "转储撤销", werks, whsLocationCode, "");
                }
            }
            return ResponseResult.success();
        } else {
            return ResponseResult.error("实际操作数量大于0的行不存在");
        }
    }

}
